package com.summer.filesync.network;

import com.summer.filesync.model.Message;
import com.summer.filesync.util.Logger;
import java.io.IOException;
import java.net.SocketTimeoutException;

/** 连接处理器 处理单个节点连接的消息接收和处理 */
public class ConnectionHandler implements Runnable {

  private static final Logger logger = Logger.getLogger(ConnectionHandler.class);

  private NodeConnection connection;
  private NetworkManager networkManager;
  private boolean running = true;

  public ConnectionHandler(NodeConnection connection, NetworkManager networkManager) {
    this.connection = connection;
    this.networkManager = networkManager;
  }

  @Override
  public void run() {
    String nodeId = connection.getNodeId();
    logger.info("Starting connection handler for node: " + nodeId);

    try {
      while (running && connection.isConnected() && networkManager.isRunning()) {
        try {
          // 接收消息
          Message message = connection.receiveMessage();

          if (message != null) {
            // 处理接收到的消息
            handleMessage(message);
          }

        } catch (SocketTimeoutException e) {
          // 超时是正常的，继续循环
          continue;
        } catch (IOException e) {
          logger.warn("Connection error with node " + nodeId + ": " + e.getMessage());
          break;
        } catch (Exception e) {
          logger.error("Unexpected error in connection handler for node " + nodeId, e);
          break;
        }
      }
    } finally {
      cleanup();
    }

    logger.info("Connection handler stopped for node: " + nodeId);
  }

  /** 处理接收到的消息 */
  private void handleMessage(Message message) {
    try {
      String sourceNodeId = message.getSourceNodeId();
      Message.MessageType type = message.getType();

      logger.debug("Handling message: " + type + " from " + sourceNodeId);

      switch (type) {
        case HEARTBEAT:
          handleHeartbeat(message);
          break;

        case NODE_LEAVE:
          handleNodeLeave(message);
          break;

        case SYNC_REQUEST:
        case SYNC_RESPONSE:
        case FILE_LIST_REQUEST:
        case FILE_LIST_RESPONSE:
        case FILE_TRANSFER_REQUEST:
        case FILE_TRANSFER_RESPONSE:
        case FILE_CHUNK:
        case FILE_TRANSFER_COMPLETE:
        case CONFLICT_DETECTED:
        case CONFLICT_RESOLUTION:
          // 将业务消息添加到队列中，由消息处理器处理
          networkManager.addIncomingMessage(message);
          break;

        default:
          logger.warn("Unknown message type: " + type + " from " + sourceNodeId);
          break;
      }

    } catch (Exception e) {
      logger.error("Error handling message: " + message, e);
    }
  }

  /** 处理心跳消息 */
  private void handleHeartbeat(Message message) {
    String sourceNodeId = message.getSourceNodeId();

    // 更新连接的心跳时间
    connection.updateLastHeartbeat();

    // 发送心跳响应
    try {
      Message heartbeatResponse =
          new Message(
              Message.MessageType.HEARTBEAT, networkManager.getLocalNodeId(), sourceNodeId, "PONG");
      connection.sendMessage(heartbeatResponse);

      logger.debug("Sent heartbeat response to: " + sourceNodeId);

    } catch (IOException e) {
      logger.error("Error sending heartbeat response to: " + sourceNodeId, e);
    }
  }

  /** 处理节点离开消息 */
  private void handleNodeLeave(Message message) {
    String sourceNodeId = message.getSourceNodeId();
    logger.info("Node leaving: " + sourceNodeId);

    // 停止此连接处理器
    running = false;

    // 通知网络管理器
    networkManager.handleConnectionLost(sourceNodeId);
  }

  /** 清理资源 */
  private void cleanup() {
    running = false;

    if (connection != null) {
      try {
        connection.close();
      } catch (Exception e) {
        logger.error("Error closing connection in cleanup", e);
      }
    }
  }

  /** 停止连接处理器 */
  public void stop() {
    running = false;
  }

  /** 检查是否正在运行 */
  public boolean isRunning() {
    return running;
  }

  /** 获取连接信息 */
  public String getConnectionInfo() {
    if (connection != null) {
      return connection.toString();
    }
    return "No connection";
  }
}
